using System;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.Xsl;
using WebServiceClientGenerator;

namespace WebServiceClientGenerator
{
    class Program
    {
        static int Main(string[] args)
        {
            try
            {
                if (args.Length == 0 || args.Length > 3)
                {
                    Usage();
                    return 1;
                }

                AppDomain currentDomain = AppDomain.CurrentDomain;
                currentDomain.AssemblyResolve += currentDomain_AssemblyResolve;

                // Load the definition
                string definitionFile = args[0];
                WebServiceClientConfig def = args.Length == 3 ?
                     WebServiceClientConfig.Load(Transform(definitionFile, args[2])) :
                     WebServiceClientConfig.Load(definitionFile);

                // Create generator
                MultiClientGenerator generator = new MultiClientGenerator(def);

                // Determine the source file name.
                string sourceFile;
                if (args.Length > 1)
                {
                    sourceFile = args[1];

                    switch (Path.GetExtension(sourceFile))
                    {
                        case ".vb":
                            generator.CodeDomProvider = new Microsoft.VisualBasic.VBCodeProvider();
                            break;
                        default:
                            break;
                    }
                }
                else
                {
                    sourceFile = DeriveSourceFile(definitionFile, generator.CodeDomProvider.FileExtension);
                }

                // Generate source file
                generator.Generate(sourceFile);

                return 0;
            } catch(Exception e)
            {
                Console.Error.WriteLine(e.Message);
                Console.Error.WriteLine(e.StackTrace);
                return 2;
            }
        }

        static Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            //This handler is called only when the common language runtime tries to bind to the assembly and fails.
	
            //Retrieve the list of referenced assemblies in an array of AssemblyName.
            Assembly MyAssembly;
            String name = args.Name;
            int index = name.IndexOf(",");
            if (index != -1) name = name.Substring(0, index);
            string strTempAssmbPath = ".\\" + name + ".dll";

            //Load the assembly from the specified path.
            MyAssembly = Assembly.LoadFrom(strTempAssmbPath);
	
            //Return the loaded assembly.
            return MyAssembly;
        }


        private static XmlReader Transform(string definitionFile, string xslFile)
        {
            XslCompiledTransform transformer = new XslCompiledTransform();
            using (Stream s = File.OpenRead(xslFile))
            {
                transformer.Load(XmlReader.Create(s));
                s.Close();
            }
            MemoryStream ms = new MemoryStream();
            using (Stream s = File.OpenRead(definitionFile))
            {
                transformer.Transform(XmlReader.Create(s), XmlWriter.Create(ms));
            }
            ms.Position = 0;
            return XmlReader.Create(ms);
        }

        private static string DeriveSourceFile(string file, string extension)
        {
            string ext = Path.GetExtension(file);
            if (!string.IsNullOrEmpty(ext))
            {
                file = file.Substring(0, file.Length - ext.Length);
            }
            return file + "." + extension;
        }

        static void Usage()
        {
            string s = 
@"Usage: WebServiceClientGenerator DefinitionFile [SourceFile] [XslFile]
    DefinitionFile:
        The XML definition file describes what Web Service client to  generate.
        If the XslFile is provide, the definition  file  is  transformed  using
        XSLT.
    SourceFile:
        Specifies the full path of the source file to be generated. If the file
        extension is not given, the default  source  file  extension  is  used.
        If this parameter is omitted,  default  to  the  definition  file  with
        extension replaced by the default source file extension.
    XslFile:
        If present, the definition file is transformed using this XSLT file.";
            Console.Error.WriteLine(s);
        }

        
    }
}